package com.mrd.gtimpframe.action;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mrd.framework.ui.Jqgrid;
import com.mrd.framework.utils.SpringUtils;
import com.mrd.gtimpframe.entity.TSysJob;
import com.mrd.gtimpframe.service.TSysJobService;
import com.mrd.schedule.ConsoleManager;
import com.mrd.schedule.core.TaskDefine;
import com.mrd.util.FormBeanUtil;
import com.mrd.util.JsonBinder;
import com.mrd.util.R;
import com.mrd.util.ResponseUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.quartz.*;
import org.quartz.impl.JobDetailImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("tSysJob")
public class TSysJobAction {
  @Autowired
  private TSysJobService tSysJobService;
  @Autowired
  SchedulerFactoryBean schedulerFactoryBean;

  @RequestMapping("listPage")
  public String listPage() {
    return "/gtimpframe/tSysJob/tSysJob";
  }

  /**
   * 列表
   */
  @RequestMapping("/list")
  public void list(Jqgrid jqgrid, HttpServletResponse response) throws Exception {
    String result = "";
    Pageable page = jqgrid.getPage();
    int pageNumber = page.getPageNumber();
    int pageSize = page.getPageSize();
    // 分页
    PageHelper.startPage(pageNumber + 1, pageSize);

    // 排序
    Sort.Order order = jqgrid.getOrder();
    if (order != null) {
      String direction = order.getDirection().toString();
      String propertyName = order.getProperty();
      PageHelper.orderBy(propertyName + " " + direction);
    }
    TSysJob tSysJob = FormBeanUtil.getEntityFromJqgrid(jqgrid, TSysJob.class);
    List<TSysJob> tSysJobList = tSysJobService.queryList(tSysJob);
    PageInfo<TSysJob> pi = new PageInfo<TSysJob>(tSysJobList);
    for (TSysJob job : tSysJobList) {
      job.setRunningStatus(check(job));
    }
    Page<Map<String, Object>> pMap = new PageImpl(tSysJobList, page, pi.getTotal());
    JsonBinder jsonBinder = JsonBinder.buildNormalBinder();
    jsonBinder.setDateFormat("yyyy-MM-dd HH:mm:ss");
    result = jsonBinder.toJson(pMap);
    ResponseUtils.renderJson(response, result);
  }

  /**
   * 保存
   *
   * @author han
   */
  @ResponseBody
  @RequestMapping("/save")
  public R save(TSysJob tSysJob) {
    tSysJob.setCreateTime(new Date());
    tSysJobService.insert(tSysJob);
    return R.ok();
  }

  /**
   * 更新
   *
   * @author han
   */
  @ResponseBody
  @RequestMapping("/update")
  public R update(TSysJob tSysJob) {
    TSysJob rtnSysJob = tSysJobService.selectByPrimaryKey(tSysJob.getJobId());
    tSysJob.setUpdateTime(new Date());
    tSysJob.setCreateTime(rtnSysJob.getCreateTime());
    tSysJobService.updateByPrimaryKey(tSysJob);
    return R.ok();
  }

  /**
   * 删除
   */
  @ResponseBody
  @RequestMapping("/delete")
  public R delete(@RequestBody String[] ids) {
    tSysJobService.deleteBatch(ids);
    return R.ok();
  }

  @ResponseBody
  @RequestMapping("/add")
  public R add(TSysJob job) {
    try {
      Scheduler scheduler = schedulerFactoryBean.getScheduler();
      TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
      CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
      MethodInvokingJobDetailFactoryBean methodInvokingJob =
          new MethodInvokingJobDetailFactoryBean();
      methodInvokingJob.setTargetObject(SpringUtils.getContext().getBean(job.getJobName()));
      methodInvokingJob.setTargetMethod(job.getBeanClass());
      methodInvokingJob.setTargetBeanName(job.getJobName());
      methodInvokingJob.setName(job.getJobName());
      methodInvokingJob.setGroup(job.getJobGroup());
      methodInvokingJob.afterPropertiesSet();// 将管理Job类提交到计划管理类
      JobDetail jobDetail = methodInvokingJob.getObject();
      jobDetail.getJobDataMap().put("scheduleJob", job);
      CronScheduleBuilder scheduleBuilder =
          CronScheduleBuilder.cronSchedule(job.getCronExpression());
      trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup())
          .withSchedule(scheduleBuilder).build();
      scheduler.scheduleJob(jobDetail, trigger);
      return R.ok();
    } catch (Exception ex) {
      return R.error("添加失败，可能调度存在多次启动");
    }
  }

  @ResponseBody
  @RequestMapping("/pouse")
  public R pouse(TSysJob job) {
    try {
      Scheduler scheduler = schedulerFactoryBean.getScheduler();
      JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
      scheduler.pauseJob(jobKey);
      return R.ok();
    } catch (SchedulerException ex) {
      return R.error(ex.getMessage());
    }
  }

  @ResponseBody
  @RequestMapping("/recover")
  public R recover(TSysJob job) {
    try {
      Scheduler scheduler = schedulerFactoryBean.getScheduler();
      JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
      scheduler.resumeJob(jobKey);
      return R.ok();
    } catch (SchedulerException ex) {
      return R.error(ex.getMessage());
    }
  }

  @ResponseBody
  @RequestMapping("/cancle")
  public R cancle(TSysJob job) {
    try {
      Scheduler scheduler = schedulerFactoryBean.getScheduler();
      TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
      scheduler.unscheduleJob(triggerKey);
      return R.ok();
    } catch (SchedulerException ex) {
      return R.error(ex.getMessage());
    }
  }

  @ResponseBody
  @RequestMapping("/check")
  public String check(TSysJob job) throws Exception {
    int stateInt = 0;
    String stateStr = "";
    Scheduler scheduler = schedulerFactoryBean.getScheduler();
    TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
    stateInt = scheduler.getTriggerState(triggerKey).ordinal();
    switch (stateInt) {
      case 5:
        stateStr = "BLOCKED";
        break;
      case 4:
        stateStr = "ERROR";
        break;
      case 3:
        stateStr = "COMPLETE";
        break;
      case 2:
        stateStr = "PAUSED";
        break;
      case 1:
        stateStr = "NORMAL";
        break;
      case 0:
        stateStr = "NONE";
        break;
    }
    return stateStr;
  }

  /**
   * 运行一次,方便调试
   * 
   * @author han
   */
  @ResponseBody
  @RequestMapping("/runOneTime")
  public R runOneTime(TSysJob job) {
    Scheduler scheduler = schedulerFactoryBean.getScheduler();
    try {
      String jobRadomName = RandomStringUtils.randomAlphanumeric(5);
      MethodInvokingJobDetailFactoryBean methodInvokingJob =
          new MethodInvokingJobDetailFactoryBean();
      methodInvokingJob.setTargetObject(SpringUtils.getContext().getBean(job.getJobName()));
      methodInvokingJob.setTargetMethod(job.getBeanClass());
      methodInvokingJob.setTargetBeanName(job.getJobName());
      methodInvokingJob.setName(job.getJobName());
      methodInvokingJob.setGroup(job.getJobGroup());
      methodInvokingJob.afterPropertiesSet();// 将管理Job类提交到计划管理类
      JobDetail jobDetail = methodInvokingJob.getObject();
      JobDetailImpl dimp = (JobDetailImpl) jobDetail;
      dimp.setName(job.getJobName() + jobRadomName);

      SimpleTrigger trigger = TriggerBuilder.newTrigger()
          .withIdentity(job.getJobName() + jobRadomName, job.getJobGroup())
          .withSchedule(
              SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).withRepeatCount(0))
          .build();
      scheduler.scheduleJob(jobDetail, trigger);

      return R.ok();
    } catch (Exception ex) {
      return R.error(ex.getMessage());
    }
  }

  @ResponseBody
  @RequestMapping("/push")
  public R push(TSysJob sysJob) {
    try {
      TaskDefine taskDefine = new TaskDefine();
      taskDefine.setTargetBean(sysJob.getJobName());
      taskDefine.setTargetMethod(sysJob.getBeanClass());
      taskDefine.setType(TaskDefine.TYPE_UNCODE_TASK);
      String cronExpression = sysJob.getCronExpression();
      if (StringUtils.isNotEmpty(cronExpression)) {
        taskDefine.setCronExpression(cronExpression);
      }
      taskDefine.setPeriod(0);
      taskDefine.setStartTime(new Date());
      if (StringUtils.isNotEmpty(cronExpression)) {
        ConsoleManager.addScheduleTask(taskDefine);
      }
      return R.ok();
    } catch (Exception ex) {
      return R.error(ex.getMessage());
    }
  }
}
